package cn.net.xyan.blossom.core.service

import cn.net.xyan.blossom.core.dao.SysVariableDao
import cn.net.xyan.blossom.core.entity.SysVariable
import cn.net.xyan.blossom.kotlin.AllOpen
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.context.WebApplicationContext

interface ConfigService{
    companion object {
        val  KEYAppRoot = "KEYAppRoot"
    }

    fun setupVariable(key:String,value:Any?,describe:String? = null): SysVariable
    fun putValue(key:String,value:Any?):SysVariable
    fun <T> queryValue(key:String,type:Class<T> ):T?
    fun <T> queryValue(key:String,type: JavaType):T?
    fun queryValue(key:String):String?
    fun findValue(key:String):SysVariable?
}

@AllOpen
class ConfigServiceImpl: ConfigService {

    @Autowired
    lateinit var sysVariableDao: SysVariableDao

    @Autowired
    lateinit var ac: WebApplicationContext

    fun objectMapper(): ObjectMapper {
        return ObjectMapper()
    }

    override fun findValue(key: String): SysVariable? {
        return sysVariableDao.findByKey(key)
    }

    @Transactional
    override fun setupVariable(key: String, value: Any?,describe:String? ): SysVariable {
        //webApplicationContext = ac
        var variable = findValue(key)
        if (variable == null){
            variable = SysVariable(key,objectMapper().writeValueAsString(value))
            variable.describe = describe
            variable = sysVariableDao.saveAndFlush(variable)
        }
        return variable!!
    }

    @Transactional
    override fun putValue(key: String, value: Any?): SysVariable {
        var variable = findValue(key)
        if (variable == null){
            variable = setupVariable(key,value)
        }else{
            variable.value = objectMapper().writeValueAsString(value)
            variable = sysVariableDao.saveAndFlush(variable)
        }
        return variable!!
    }

    override fun <T> queryValue(key: String, type: Class<T>): T? {
        var variable = findValue(key) ?: return null

        if(variable.value == null)
            return null
        return objectMapper().readValue(variable.value,type)
    }

    override fun <T> queryValue(key: String, type: JavaType): T? {
        var variable = findValue(key)
        if(variable!!.value == null)
            return null
        return objectMapper().readValue(variable.value,type)
    }

    override fun queryValue(key: String): String? {
        return queryValue(key,String::class.java)
    }

}